import numpy as np
import hashlib
import json
from datetime import datetime, timedelta

class GDPRCompliance:
    """
    GDPR合规管理模块
    实现数据匿名化、访问控制和审计跟踪
    """
    def __init__(self, epsilon=0.3):
        self.epsilon = epsilon  # 差分隐私参数
        self.audit_logs = []    # 审计日志
        self.data_retention_period = 365  # 数据保留期：365天
        self.anonymization_methods = {
            'user_id': self._anonymize_id,
            'timestamp': self._anonymize_timestamp,
            'features': self._anonymize_features,
            'text': self._anonymize_text
        }
        
        # 数据访问控制列表
        self.access_control = {
            'admin': ['read', 'write', 'delete', 'export'],
            'analyst': ['read', 'export'],
            'system': ['read', 'write'],
            'user': ['read', 'delete']
        }
        
        # AI决策日志保留策略 (ISO/IEC 23894合规)
        self.ai_decision_retention = 90  # 90天
        
    def _anonymize_id(self, user_id):
        """匿名化用户ID"""
        # 使用盐值哈希确保不可逆性
        salt = "hsync_gdpr_salt_2023"  # 在实际部署中应使用安全的随机盐值
        return hashlib.sha256(f"{user_id}{salt}".encode()).hexdigest()
    
    def _anonymize_timestamp(self, timestamp, granularity='day'):
        """匿名化时间戳，降低精度"""
        dt = datetime.fromtimestamp(timestamp)
        
        if granularity == 'day':
            # 精确到天
            return dt.replace(hour=0, minute=0, second=0, microsecond=0).timestamp()
        elif granularity == 'hour':
            # 精确到小时
            return dt.replace(minute=0, second=0, microsecond=0).timestamp()
        else:
            # 精确到分钟
            return dt.replace(second=0, microsecond=0).timestamp()
    
    def _anonymize_features(self, features):
        """
        使用拉普拉斯机制匿名化特征向量
        实现差分隐私
        """
        features = np.array(features)
        # 计算敏感度（假设特征已归一化到[0,1]）
        sensitivity = 1.0
        
        # 生成拉普拉斯噪声
        noise = np.random.laplace(loc=0.0, scale=sensitivity/self.epsilon, size=features.shape)
        
        # 添加噪声并裁剪到有效范围
        anonymized = features + noise
        return np.clip(anonymized, 0.0, 1.0)
    
    def _anonymize_text(self, text, replacement='[REDACTED]'):
        """匿名化文本中的个人身份信息"""
        # 简单实现：替换可能包含PII的模式
        # 在实际应用中应使用更复杂的NLP模型
        patterns = [
            # 电子邮件
            (r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', replacement),
            # 电话号码（简单模式）
            (r'\b\d{3}[-.\s]?\d{3}[-.\s]?\d{4}\b', replacement),
            # 信用卡号（简单模式）
            (r'\b(?:\d{4}[-\s]?){3}\d{4}\b', replacement)
        ]
        
        anonymized_text = text
        for pattern, repl in patterns:
            import re
            anonymized_text = re.sub(pattern, repl, anonymized_text)
        
        return anonymized_text
    
    def _log_access(self, user_id, action, data_type, success=True):
        """记录数据访问日志"""
        log_entry = {
            'timestamp': datetime.now().timestamp(),
            'user_id': self._anonymize_id(user_id),  # 匿名化操作人ID
            'action': action,
            'data_type': data_type,
            'success': success,
            'ip_address': 'anonymous'  # 在实际应用中记录IP但可能需要匿名化
        }
        
        self.audit_logs.append(log_entry)
        
        # 清理过期日志（保留1年）
        one_year_ago = (datetime.now() - timedelta(days=365)).timestamp()
        self.audit_logs = [log for log in self.audit_logs if log['timestamp'] >= one_year_ago]
    
    def check_access(self, user_role, action):
        """检查用户是否有权限执行特定操作"""
        if user_role not in self.access_control:
            return False
            
        return action in self.access_control[user_role]
    
    def process_data(self, data, user_id, data_type, user_role='system'):
        """
        处理数据以符合GDPR要求
        包括匿名化和访问控制
        """
        # 检查访问权限
        if not self.check_access(user_role, 'write'):
            self._log_access(user_id, 'write', data_type, success=False)
            raise PermissionError(f"用户角色 {user_role} 没有权限写入 {data_type} 数据")
        
        # 记录访问
        self._log_access(user_id, 'write', data_type)
        
        # 复制数据以避免修改原始数据
        processed_data = data.copy() if isinstance(data, dict) else data
        
        # 应用适当的匿名化
        if isinstance(processed_data, dict):
            for key, value in processed_data.items():
                if key in self.anonymization_methods:
                    processed_data[key] = self.anonymization_methods[key](value)
        
        # 添加数据生命周期信息
        if isinstance(processed_data, dict):
            processed_data['data_processed_at'] = datetime.now().timestamp()
            processed_data['data_expires_at'] = (datetime.now() + 
                                               timedelta(days=self.data_retention_period)).timestamp()
        
        return {
            'processed_data': processed_data,
            'anonymization_method': f"differential_privacy(epsilon={self.epsilon})",
            'retention_period_days': self.data_retention_period,
            'audit_id': len(self.audit_logs) - 1  # 引用审计日志
        }
    
    def export_user_data(self, user_id, requester_role):
        """
        导出用户数据（GDPR第15条：访问权）
        允许用户获取其个人数据的副本
        """
        # 检查访问权限
        if not self.check_access(requester_role, 'export'):
            self._log_access(requester_role, 'export', 'user_data', success=False)
            raise PermissionError(f"用户角色 {requester_role} 没有权限导出用户数据")
        
        # 在实际应用中，这里会查询数据库获取用户数据
        # 此处仅为示例
        user_data = {
            'user_id': self._anonymize_id(user_id),
            'data_points': 156,
            'last_processed': datetime.now().timestamp() - 3600,
            'data_categories': ['behavioral', 'preferences', 'interaction']
        }
        
        # 记录访问
        self._log_access(requester_role, 'export', 'user_data')
        
        return {
            'user_data': user_data,
            'export_timestamp': datetime.now().timestamp(),
            'data_format': 'json',
            'audit_id': len(self.audit_logs) - 1
        }
    
    def delete_user_data(self, user_id, requester_role):
        """
        删除用户数据（GDPR第17条：被遗忘权）
        允许用户要求删除其个人数据
        """
        # 检查访问权限
        if not self.check_access(requester_role, 'delete'):
            self._log_access(requester_role, 'delete', 'user_data', success=False)
            raise PermissionError(f"用户角色 {requester_role} 没有权限删除用户数据")
        
        # 在实际应用中，这里会执行数据库删除操作
        # 此处仅为示例
        deletion_result = {
            'user_id': self._anonymize_id(user_id),
            'records_deleted': 156,
            'categories_deleted': ['behavioral', 'preferences', 'interaction']
        }
        
        # 记录访问
        self._log_access(requester_role, 'delete', 'user_data')
        
        return {
            'deletion_result': deletion_result,
            'deletion_timestamp': datetime.now().timestamp(),
            'audit_id': len(self.audit_logs) - 1
        }
    
    def get_audit_trail(self, user_role, start_date=None, end_date=None):
        """获取审计跟踪日志"""
        # 检查访问权限
        if not self.check_access(user_role, 'read'):
            self._log_access(user_role, 'read', 'audit_logs', success=False)
            raise PermissionError(f"用户角色 {user_role} 没有权限访问审计日志")
        
        # 过滤日志
        filtered_logs = self.audit_logs
        
        if start_date:
            start_ts = start_date.timestamp()
            filtered_logs = [log for log in filtered_logs if log['timestamp'] >= start_ts]
        
        if end_date:
            end_ts = end_date.timestamp()
            filtered_logs = [log for log in filtered_logs if log['timestamp'] <= end_ts]
        
        # 记录访问
        self._log_access(user_role, 'read', 'audit_logs')
        
        return {
            'logs': filtered_logs,
            'count': len(filtered_logs),
            'export_timestamp': datetime.now().timestamp()
        }
    
    def log_ai_decision(self, decision_data):
        """记录AI决策用于审计（ISO/IEC 23894合规）"""
        """记录AI决策用于审计（ISO/IEC 23894合规）"""
        decision_log = {
            'timestamp': datetime.now().timestamp(),
            'decision_id': hashlib.md5(json.dumps(decision_data, sort_keys=True).encode()).hexdigest(),
            'decision_type': decision_data.get('type', 'unknown'),
            'inputs': self._anonymize_features(decision_data.get('inputs', [])),
            'output': decision_data.get('output', ''),
            'confidence': decision_data.get('confidence', 0.0),
            'expires_at': (datetime.now() + timedelta(days=self.ai_decision_retention)).timestamp()
        }
        
        # 在实际应用中，这会存储在专门的AI决策日志系统中
        self.audit_logs.append(decision_log)
        
        return decision_log['decision_id']
    